package com.test.service;

import com.google.common.collect.Lists;
import com.test.entity.Order;
import com.test.repository.OrderMapper;
import com.test.repository.OrderRepository;
import com.test.representation.OrderRepresentation;
import com.test.representation.UserRepresentation;
import io.shardingsphere.core.api.HintManager;
import io.shardingsphere.core.keygen.KeyGenerator;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * Created by lichangbin@xwbank.com on 2018/7/2
 */
@Slf4j
@RequiredArgsConstructor
@Transactional
@Service
public class OrderService {

  private final AtomicInteger COUNTER = new AtomicInteger(100000);

  private final UserService userService;

  private final OrderRepository orderRepository;
  private final OrderMapper orderMapper;

  private final KeyGenerator keyGenerator;

  public OrderRepresentation getByOrderNumber(String orderNumber) {
    List<Order> orders = generateOrders();
    orderNumber = orders.get(0).getOrderNumber();
    final int orderNumberLength = orderNumber.length();
    final long shardingValue = NumberUtils
        .toLong(StringUtils.substring(orderNumber, orderNumberLength - 4, orderNumberLength));
    try (HintManager hintManager = HintManager.getInstance()) {
      hintManager
          .addDatabaseShardingValue("order", "user_id", shardingValue);
      return orderRepresentation(orderRepository.findByOrderNumber(orderNumber));
    }
  }

  public List<OrderRepresentation> getByUserId(Long userId) {
    List<Order> orders = generateOrders();
    return orderRepository.findByUserId(orders.get(0).getUserId()).stream()
        .map(this::orderRepresentation).collect(Collectors.toList());
  }


  private OrderRepresentation orderRepresentation(Order order) {
    OrderRepresentation representation = new OrderRepresentation();
    BeanUtils.copyProperties(order, representation);
    return representation;
  }

  private List<Order> generateOrders() {
    orderRepository.deleteAll();
    List<UserRepresentation> users = userService.findByPagination(5);
    List<Order> orders = Lists.newArrayList();
    for (UserRepresentation user : users) {
      for (int i = 0; i < 2; i++) {
        Order order = new Order();
        order.setId(keyGenerator.generateKey().longValue());
        order.setUserId(user.getUserId());
        order.setAmount(BigDecimal.valueOf(RandomUtils.nextDouble(10.00, 20.00))
            .setScale(2, RoundingMode.HALF_DOWN));
        final String userId = String.valueOf(user.getUserId());
        final int length = userId.length();
        order.setOrderNumber(COUNTER.incrementAndGet() + StringUtils
            .substring(userId, length - 4, length));
        orders.add(order);
      }
    }
    orderRepository.insert(orders.toArray(new Order[orders.size()]));
    return orders;
  }
}
